#include <stdio.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include "ohos_init.h"
#include "cmsis_os2.h"
#include "iot_gpio.h"
#include "temp-humi_sensor.h"
#include "aht20.h"


#include "MQTTClient.h" //mqtt三方库
#include "cJSON.h"      //cJson解析三方库



#include "wifi_connecter.h" // easy wifi (station模式)
#include "iot_watchdog.h" 
#include "hi_io.h"

#define GPIO_LED 9


// 定义一个宏，用于标识SSID。请根据实际情况修改
#define PARAM_HOTSPOT_SSID "w"

// 定义一个宏，用于标识密码。请根据实际情况修改
#define PARAM_HOTSPOT_PSK "12345678"

// 定义一个宏，用于标识加密方式
#define PARAM_HOTSPOT_TYPE WIFI_SEC_TYPE_PSK



// 定义一个宏，用于标识MQTT服务器IP地址。请根据实际情况修改
#define HOST_ADDR "59e62b5755.st1.iotda-device.cn-north-4.myhuaweicloud.com"

// 定义一个宏，用于标识MQTT服务器端口
#define HOST_PORT 1883

// 定义一个宏，用于标识智能家居的设备ID
#define DEVICE_ID "67eb96a85367f573f77e8956_DEVICE-TEST-001"
// 定义一个宏，用于标识用于MQTT连接的clientid
#define MQTT_CLIENT_ID "67eb96a85367f573f77e8956_DEVICE-TEST-001_0_0_2025040706"

// 定义一个宏，用于标识用于MQTT连接的username
#define MQTT_USERNAME "67eb96a85367f573f77e8956_DEVICE-TEST-001"

// 定义一个宏，用于标识用于MQTT连接的password
#define MQTT_PASSWORD "a0e87ed814b750a189fcfbc1206361c668c9ac87e90a6a66f51ce1ff02613e82"



// 定义一个宏，用于标识设备属性上报所用的topic
#define PUBLISH_TOPIC "$oc/devices/"DEVICE_ID"/sys/properties/report"
// 定义一个宏，用于标识订阅下发命令所用的topic
#define SUBCRIB_TOPIC "$oc/devices/"DEVICE_ID"/sys/commands/#" 
// 定义一个宏，用于标识执行完成下发命令所返回响应的topic
#define RESPONSE_TOPIC "$oc/devices/"DEVICE_ID"/sys/commands/response" 

//定义用于mqtt连接的两个对象变量，对象类型来自mqtt三方库
Network network;    
MQTTClient client;

static unsigned char sendBuf[1000];
static unsigned char readBuf[1000];

// 假设这是您定义的结构体，用于存储AHT20传感器数据
typedef struct {
    float temperature; // 存储温度值
    float humidity;    // 存储湿度值
} SensorData;

// 假设这是读取AHT20传感器数据的函数
uint32_t SensorReadData1(SensorData *data) {
     //初始化温湿度传感器
   InitTempHumiSensor();
    // 调用AHT20传感器的接口获取数据
    uint32_t retval1 =GetTempHumiLevel(&data->temperature, &data->humidity);
    printf("temperature: %lf, humidity: %lf\n", data->temperature, data->humidity);
    return retval1; // 返回操作结果
}

static void get_sensor_public_string(char *payload) {
    MQTTMessage message;
    SensorData data = {0}; // 初始化SensorData结构体

    // 读取AHT20传感器数据
    if (SensorReadData1(&data) == 0) {
        //--将读取到的AHT20传感器数据封装成上华为云iot平台的数据结构--start
        cJSON *root = cJSON_CreateObject(); // 创建JSON对象

        if (root != NULL) {
            // 创建数组，用于存放服务数据
            cJSON *serv_arr = cJSON_AddArrayToObject(root, "services");

            // 创建数组项，代表单个服务
            cJSON *arr_item = cJSON_CreateObject();

            // 添加服务ID
            cJSON_AddStringToObject(arr_item, "service_id", "service01");

            // 创建对象，用于存放属性
            cJSON *pro_obj = cJSON_CreateObject();
            cJSON_AddItemToObject(arr_item, "properties", pro_obj);

            // 添加温度和湿度数据到属性对象
            cJSON_AddNumberToObject(pro_obj, "temperature", data.temperature);
            cJSON_AddNumberToObject(pro_obj, "humidity", data.humidity);

            // 将服务数组项添加到服务数组中
            cJSON_AddItemToArray(serv_arr, arr_item);

            // 将JSON对象转换为字符串
            char *payload_str = cJSON_PrintUnformatted(root);
            if (payload_str != NULL) {
                strcpy(payload, payload_str); // 将JSON字符串复制到payload
                cJSON_free(payload_str); // 释放cJSON分配的内存
            }

            // 删除JSON对象，释放内存
            cJSON_Delete(root);
        }
        //--将读取到的AHT20传感器数据封装成上华为云iot平台的数据结构--end
    } else {
        // 处理读取传感器数据失败的情况
        printf("Failed to read data from AHT20 sensor.\n");
    }
}


//云端下发的控制命令响应函数
void messageArrived(MessageData* data)
{
    int rc;
    printf("Message arrived on topic %.*s: %.*s\n", data->topicName->lenstring.len, data->topicName->lenstring.data,
           data->message->payloadlen, data->message->payload);
    //此处处理收到云端发送过来的命令，在此处编写处理命令的业务逻辑，实现电机的转动和停止
       cJSON *root = cJSON_ParseWithLength( data->message->payload, data->message->payloadlen);
    if(root != NULL){
        cJSON *cmd_name = cJSON_GetObjectItem(root,"command_name");
        if(cmd_name != NULL){
            char *cmd_name_str = cJSON_GetStringValue(cmd_name);
            if(strcmp(cmd_name_str,"cmd") == 0){
                 cJSON *para_obj = cJSON_GetObjectItem(root,"paras");
                 if(para_obj){
                      cJSON *lightParam = cJSON_GetObjectItem(para_obj,"led");
                      if(strcmp(cJSON_GetStringValue(lightParam),"ON") == 0){
                        // Motor_Start();		//开始转动电机
                                IoTGpioSetOutputVal(GPIO_LED,IOT_GPIO_VALUE0);
                      }else{
                        // Motor_Stop();		//停止转动电机
                                IoTGpioSetOutputVal(GPIO_LED,IOT_GPIO_VALUE1);
                      }
                 }
            }
        }

        cJSON_Delete(root);
    }
}

static void MQTTDemoTask(void)
{
//     //初始化温湿度传感器
//    InitTempHumiSensor();

    printf(">> MQTTDemoTask ...\n");
    // 连接AP
    // 定义热点配置
    WifiDeviceConfig config = {0};
    // 设置热点配置中的SSID
    strcpy(config.ssid, PARAM_HOTSPOT_SSID);
    // 设置热点配置中的密码
    strcpy(config.preSharedKey, PARAM_HOTSPOT_PSK);
    // 设置热点配置中的加密方式
    config.securityType = PARAM_HOTSPOT_TYPE;
    // 等待100ms
    osDelay(10);
    // 连接到热点
    int netId = ConnectToHotspot(&config);

    printf("wifi connect successful !\n");
    
    // 检查是否成功连接到热点
    if (netId < 0)
    {
        printf("Connect to AP failed!\r\n");
        return;
    }

    // 初始化并启动MQTT任务，连接MQTT服务器
  int rc, count = 0;
begin:   
    //初始化NetworkInit
    NetworkInit(&network);
    // 连接网络
    NetworkConnect(&network, HOST_ADDR, HOST_PORT);


    printf("MQTTClientInit  ...\n");

    MQTTClientInit(&client, &network, 2000, sendBuf, sizeof(sendBuf), readBuf, sizeof(readBuf));

    MQTTString clientId = MQTTString_initializer;
    clientId.cstring = MQTT_CLIENT_ID;
    MQTTString userName = MQTTString_initializer;
    userName.cstring = MQTT_USERNAME;
    MQTTString password = MQTTString_initializer;
    password.cstring = MQTT_PASSWORD;
    MQTTPacket_connectData data = MQTTPacket_connectData_initializer;
    data.clientID = clientId;
    data.username = userName;
	data.password = password;
    data.willFlag = 0;
    data.MQTTVersion = 4;
    data.keepAliveInterval = 600;
    data.cleansession = 1;
    printf("MQTTConnect  ...\n");

    rc = MQTTConnect(&client, &data);
    if (rc != 0) {
        printf("MQTTConnect: %d\n", rc);
        NetworkDisconnect(&network);
        MQTTDisconnect(&client);
         goto begin;
    }

    printf("MQTTSubscribe  ...\n");
    rc = MQTTSubscribe(&client, SUBCRIB_TOPIC, 0, messageArrived);
    while (1) {
        MQTTMessage message;
		char payload[500]={0};
        // get_sensor_public_string(payload);
     
        message.qos = 0;
        message.retained = 0;
        message.payload = payload;
     
        message.payloadlen = strlen(payload);

        if ((rc = MQTTPublish(&client, PUBLISH_TOPIC, &message)) != 0) {
            printf("Return code from MQTT publish is %d\n", rc);
            NetworkDisconnect(&network);
            MQTTDisconnect(&client);
            goto begin;
        }else{
            printf("mqtt publish success:%s\n",payload);
        }
        MQTTYield(&client, 5000);
    }
}  



static void OC_Demo(void)
{
    IoTWatchDogDisable();
    IoTGpioInit(GPIO_LED);
    hi_io_set_func(GPIO_LED, HI_IO_FUNC_GPIO_9_GPIO);
    IoTGpioSetDir(GPIO_LED,IOT_GPIO_DIR_OUT);

    osThreadAttr_t attr;
    



    attr.name = "MQTTDemoTask";
    attr.attr_bits = 0U;
    attr.cb_mem = NULL;
    attr.cb_size = 0U;
    attr.stack_mem = NULL;
    attr.stack_size = 10240;
    attr.priority = 24;

    if (osThreadNew((osThreadFunc_t)MQTTDemoTask, NULL, &attr) == NULL)
    {
        printf("Falied to create MQTTDemoTask!\n");
    }

}

APP_FEATURE_INIT(OC_Demo);
//SYS_RUN(OC_Demo);
